/*
JETware Hands-free Extension provides additional features for Windows Mobile HFP support.
Copyright (C) 2004-2009 Jim Thatcher

This program is free software; you can redistribute it and/or modify it under the terms of the 
GNU General Public License as published by the Free Software Foundation; version 2 of the License.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; 
if not, write to the Free Software Foundation, Inc., 
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

Source Control header

$Workfile: DeviceSettings.cpp $
$Revision: 1 $
$Date: 1/1/09 1:11p $
*/
#include "JetBTConfig.h"

#define TOKEN_EOF		-1
#define TOKEN_NONE		0
#define TOKEN_WHTSPC	1
#define TOKEN_DEVICE	2
#define TOKEN_COMMENT	3
#define TOKEN_SETTING	4
#define TOKEN_VALUE		5
#define TOKEN_STRING	6
#define JETWARE_KEY		_T("SOFTWARE\\JETware\\AGext")

BOOL CALLBACK ChooseDeviceDialogProc(const HWND hDlg, const UINT uiMessage, const WPARAM wParam, const LPARAM lParam);

void GetLocalDeviceName(HWND hParent, TCHAR * szDevName, TCHAR * szLocalName)
{
	TCHAR szValue[MAX_PATH];
	WORD wFlags = HWINFO_OEM;
	// Read from TAPI
	// Default is to return same string - Either found a match or user want's to use this name
#ifdef DEBUG
	CHAR szLog[128];
	sprintf(szLog, "GetLocalDeviceName of %S", szDevName);
	LogString(szLog);
#endif
	wcscpy(szLocalName, szDevName);
	while (wFlags >= HWINFO_MFR)
	{
		szValue[0] = 0;
		ReadHardwareDeviceString(szValue, wFlags);
		if (szValue[0] != 0)
		{
			if (wcscmp(szValue, szDevName) == 0)
			{
				// it matches the phone name, so we are done
				return;
			}
		}
		wFlags--;
	}
#ifdef DEBUG
	LogString("Launching Choose Device dialog");
#endif
	SetCursor(NULL);
	int nResult = DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_CHOOSEDEVICE), hParent, (DLGPROC)ChooseDeviceDialogProc, (LPARAM) szLocalName);
	SetCursor(LoadCursor(NULL, IDC_WAIT));
	return;
}

TCHAR * szDeviceName = NULL;


BOOL AddDeviceSettings(HWND hWnd, TCHAR * szFilename)
{
#ifdef DEBUG
	CHAR szLog[256];
	sprintf(szLog, "Importing %S", szFilename);
	LogString(szLog);
#endif
	BOOL bReturn = FALSE;
	HANDLE h;
	Sleep(100); // Give download process time to release file
	h = CreateFile(szFilename, GENERIC_READ, 0,
		NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if (h != INVALID_HANDLE_VALUE)
	{
		TCHAR	szInput[2048];
		DWORD	dwRead = 0;		// Number of bytes read from file
		DWORD	dwParsed = 0;	// Number of TCHARs parsed from buffer
		TCHAR	szValueName[MAX_PATH];
		TCHAR	szValueString[MAX_PATH];
		DWORD	dwValueSize = 0;
		HRESULT hr                  = S_OK;
		HKEY    hRootKey            = NULL;
		HKEY    hDeviceKey          = NULL;
		DWORD   dwType              = 0;
		DWORD	dwSize				= 0;
		DWORD	dwValue				= 0;
		WORD	wToken				= TOKEN_NONE;

		hr = RegOpenKeyEx(HKEY_LOCAL_MACHINE, JETWARE_KEY, 0, 0, &hRootKey);
		if (ERROR_SUCCESS == hr)
		{
			SetCursor(LoadCursor(NULL, IDC_WAIT));
			BOOL bRet = ReadFile(h, szInput, sizeof(szInput), &dwRead, NULL);
			if (!bRet)
				bReturn = FALSE;
			TCHAR * pCurr = szInput;
			while (bRet && dwRead)
			{
#ifdef DEBUG
				sprintf(szLog, "Read data: %S", szInput);
				LogString(szLog);
#endif
				if (hDeviceKey == NULL)
				{
					if (wToken != TOKEN_DEVICE)
					{
						wToken = TOKEN_NONE;
						// Find device name
						while ((*pCurr != '[') && (dwParsed < (dwRead*2)))
						{
							pCurr++;
							dwParsed++;
						}
						// Advance past bracket
						pCurr++;
						dwParsed++;
					}
					wToken = TOKEN_DEVICE;
					szValueName[0] = 0;
					dwValueSize = 0;
					while ((*pCurr != ']') && (dwParsed < (dwRead*2)))
					{
						szValueName[dwValueSize++] = *pCurr++;
						dwParsed++;
					}
					if (*pCurr == ']')
					{
						TCHAR szDeviceName[256];
						szValueName[dwValueSize] = 0;
						// Advance past bracket
						pCurr++;
						dwParsed++;
						wToken = TOKEN_NONE;
#ifdef DEBUG
						sprintf(szLog, "Found device %S", szValueName);
						LogString(szLog);
#endif
						if (lstrcmp(szValueName, _T("Root")) == 0)
							szDeviceName[0] = 0; // Make it an empty string so we open sub key to AGExt root
						else
						{
							GetLocalDeviceName(hWnd, szValueName, szDeviceName);
						}
						hr = RegCreateKeyEx(hRootKey, szDeviceName, 0, NULL, 0, 0, NULL, &hDeviceKey, &dwType);
					}
				}
				if ((hDeviceKey == NULL) && (dwRead < sizeof(szInput)))
					break;
				if (hDeviceKey != NULL)
				{
					while (dwParsed < (dwRead*2))
					{
						if (wToken >= TOKEN_COMMENT) // finish reading after refilling buffer
						{
							switch (wToken)
							{
								case TOKEN_COMMENT: // comment - skip rest of line
									dwValueSize = 0;
									while ((*pCurr != '\r') && (dwParsed < (dwRead*2)))
									{
										pCurr++;
										dwParsed++;
									}
									if (dwParsed < (dwRead*2))
										wToken = TOKEN_NONE;
									break;
								case TOKEN_VALUE: // setting value
									dwValue = 0; //TODO: Do we need to continue in case we emptied the buffer in the middle of a value?
									while ((*pCurr >= '0') && (*pCurr <= '9') && (dwParsed < (dwRead*2)))
									{
										dwValue = (dwValue * 10) + (*pCurr - '0');
										pCurr++;
										dwParsed++;
									}
									if (dwParsed < (dwRead*2))
									{
										wToken = TOKEN_NONE;
#ifdef DEBUG
										sprintf(szLog, "Found setting %ls = %i", szValueName, dwValue);
										LogString(szLog);
#endif
										RegSetValueEx(hDeviceKey, szValueName, 0, REG_DWORD, (LPBYTE) &dwValue, sizeof(DWORD));
										szValueName[0] = 0;
										dwValue = 0;
										bReturn = TRUE;
									}
									break;
								case TOKEN_STRING: // setting string value - Already past opening "
									// szValueString[0] = 0; //TODO: Do we need to continue in case we emptied the buffer in the middle of a value?
									// dwValueSize = 0;
									while ((*pCurr != '"') && (dwParsed < (dwRead*2)))
									{
										szValueString[dwValueSize++] = *pCurr++;
										dwParsed++;
									}
									szValueString[dwValueSize++] = 0; // terminate the string
									if (dwParsed < (dwRead*2))
									{
										wToken = TOKEN_NONE;
										pCurr++;
										dwParsed++;
#ifdef DEBUG
										sprintf(szLog, "Found setting %ls = %ls", szValueName, szValueString);
										LogString(szLog);
#endif
										RegSetValueEx(hDeviceKey, szValueName, 0, REG_SZ, (LPBYTE) &szValueString, dwValueSize * sizeof(TCHAR));
										szValueName[0] = 0;
										dwValueSize = 0;
										bReturn = TRUE;
									}
									break;
								case TOKEN_SETTING:
								default: // value name
									szValueName[0] = 0;
									dwValueSize = 0;
									while ((*pCurr != '=') && (dwParsed < (dwRead*2)))
									{
										szValueName[dwValueSize++] = *pCurr++;
										dwParsed++;
									}
									if (dwParsed < (dwRead*2))
									{
										wToken = TOKEN_NONE;
										szValueName[dwValueSize] = 0;
									}
									break;
							}
						}
						switch (*pCurr)
						{
							case '\r':
							case '\n':
							case '\t': // skip white space
								wToken = TOKEN_WHTSPC;
								pCurr++;
								dwParsed++;
								break;
							case '[': // Begin new device settings
								pCurr++;
								dwParsed++;
								wToken = TOKEN_DEVICE;
								RegCloseKey(hDeviceKey);
								hDeviceKey = NULL;
								break;
							case ';': // comment - skip rest of line
								wToken = TOKEN_COMMENT;
								dwValueSize = 0;
								while ((*pCurr != '\r') && (dwParsed < (dwRead*2)))
								{
									pCurr++;
									dwParsed++;
								}
								if (dwParsed < (dwRead*2))
									wToken = TOKEN_NONE;
								break;
							case '=': // setting value
								pCurr++;
								dwParsed++;
								if (*pCurr == '"')
								{
									wToken = TOKEN_STRING;
									pCurr++;
									dwParsed++;
									szValueString[0] = 0;
									dwValueSize = 0;
									while ((*pCurr != '"') && (dwParsed < (dwRead*2)))
									{
										szValueString[dwValueSize++] = *pCurr++;
										dwParsed++;
									}
									szValueString[dwValueSize++] = 0; // terminate the string
									if (dwParsed < (dwRead*2))
									{
										wToken = TOKEN_NONE;
										pCurr++;
										dwParsed++;
#ifdef DEBUG
										sprintf(szLog, "Found setting %ls = %ls", szValueName, szValueString);
										LogString(szLog);
#endif
										RegSetValueEx(hDeviceKey, szValueName, 0, REG_SZ, (LPBYTE) &szValueString, dwValueSize * sizeof(TCHAR));
										szValueName[0] = 0;
										dwValueSize = 0;
										bReturn = TRUE;
									}
								}
								else
								{
									wToken = TOKEN_VALUE;
									dwValue = 0;
									while ((*pCurr >= '0') && (*pCurr <= '9') && (dwParsed < (dwRead*2)))
									{
										dwValue = (dwValue * 10) + (*pCurr - '0');
										pCurr++;
										dwParsed++;
									}
									if (dwParsed < (dwRead*2))
									{
										wToken = TOKEN_NONE;
#ifdef DEBUG
										sprintf(szLog, "Found setting %S = %i", szValueName, dwValue);
										LogString(szLog);
#endif
										RegSetValueEx(hDeviceKey, szValueName, 0, REG_DWORD, (LPBYTE) &dwValue, sizeof(DWORD));
										szValueName[0] = 0;
										bReturn = TRUE;
									}
								}
								break;
							default: // value name
								wToken = TOKEN_SETTING;
								szValueName[0] = 0;
								dwValueSize = 0;
								while ((*pCurr != '=') && (dwParsed < (dwRead*2)))
								{
									szValueName[dwValueSize++] = *pCurr++;
									dwParsed++;
								}
								if (dwParsed < (dwRead*2))
								{
									wToken = TOKEN_NONE;
									szValueName[dwValueSize] = 0;
								}
								break;
						}
						if (hDeviceKey == NULL)
							break;
					}
				}
				if (dwParsed >= (dwRead*2))
				{
					// there may be more data available
					bRet = ReadFile(h, szInput, sizeof(szInput), &dwRead, NULL);
					pCurr = szInput;
					dwParsed = 0;
				}
			}
			if (hDeviceKey != NULL)
				RegCloseKey(hDeviceKey);
			RegCloseKey(hRootKey);
			SetCursor(NULL);

		}
#ifdef DEBUG
		else
		{
			sprintf(szLog, "RegOpenKey failed %8.8X", hr);
			LogString(szLog);
		}
#endif
		CloseHandle(h);
	}
#ifdef DEBUG
	else
	{
		sprintf(szLog, "CreateFile failed %8.8X", GetLastError());
		LogString(szLog);
	}
#endif
	return(bReturn);
}